package com.ashin.plugin;

import com.ashin.context.LanguageContext;
import com.ashin.entity.AccountI18n;
import com.ashin.mapper.AccountI18NMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
//        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
@Component
public class MyInterceptor implements Interceptor, ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
        SqlCommandType sqlCommandType = ms.getSqlCommandType();
        System.out.println(sqlCommandType);
        if (SqlCommandType.DELETE == sqlCommandType) {
            System.out.println("删除不做处理");
            return invocation.proceed();
        }

        Object result = invocation.proceed();

        if (SqlCommandType.INSERT == sqlCommandType) {
            // 同步到国际化表
            // 判断是否需要同步
            Object entity = invocation.getArgs()[1];
            TranslateClass annotation = entity.getClass().getAnnotation(TranslateClass.class);
            if (annotation == null) {
                System.out.println("插入，无需同步国际化表");
                return result;
            }

            Field[] declaredFields = entity.getClass().getDeclaredFields();
            List<Field> fieldList = Arrays.stream(declaredFields).filter(field -> field.getAnnotation(TranslateField.class) != null).collect(Collectors.toList());
            if (fieldList.isEmpty()) {
                System.out.println("没有需要翻译的字段，无需翻译");
                return result;
            }

            Optional<Field> idFieldOpt = Arrays.stream(declaredFields).filter(field -> field.getAnnotation(TranslateBusinessId.class) != null).findFirst();
            if (!idFieldOpt.isPresent()) {
                System.out.println("没id无需翻译");
                return result;
            }

            Field field = idFieldOpt.get();
            field.setAccessible(true);
            String businessId = String.valueOf(field.get(entity));

            AccountI18NMapper accountI18NMapper = applicationContext.getBean(AccountI18NMapper.class);
            for (Field translateField : fieldList) {
                translateField.setAccessible(true);
                AccountI18n accountI18n = new AccountI18n();
                accountI18n.setBusinessId(businessId);
                accountI18n.setLang(LanguageContext.getLanguage());
                accountI18n.setLangKey(translateField.getName());
                accountI18n.setLangValue(String.valueOf(translateField.get(entity)));

                accountI18NMapper.insert(accountI18n);
            }

            return result;
        }
//
        if (SqlCommandType.UPDATE == sqlCommandType) {
            // 更新记录记录， 更新涉及多条记录的情况，只能是一条记录
            if ((Integer) result != 1) {
                System.out.println("更新记录只能一条成功的情况");
                return result;
            }
            // 更新的字段是否需要翻译，


            // 同步到国际化表
            Object parameter = invocation.getArgs()[1];

            Map<String, Object> paramMap = (Map) parameter;
            List<Object> parameters = new ArrayList();
            paramMap.keySet().forEach((key) -> {
                if (key.startsWith("param")) {
                    parameters.add(paramMap.get(key));
                }
            });


            Object entity = null;
            TranslateClass annotation = entity.getClass().getAnnotation(TranslateClass.class);
            if (annotation == null) {
                System.out.println("更新，无需同步国际化表");
                return result;
            }

            Field[] declaredFields = entity.getClass().getDeclaredFields();
            List<Field> fieldList = Arrays.stream(declaredFields).filter(field -> field.getAnnotation(TranslateField.class) != null).collect(Collectors.toList());
            if (fieldList.isEmpty()) {
                System.out.println("更新 没有需要翻译的字段，无需翻译");
                return result;
            }

            Optional<Field> idFieldOpt = Arrays.stream(declaredFields).filter(field -> field.getAnnotation(TranslateBusinessId.class) != null).findFirst();
            if (!idFieldOpt.isPresent()) {
                System.out.println("更新 没id无需翻译");
                return result;
            }

            Field field = idFieldOpt.get();
            field.setAccessible(true);
            String businessId = String.valueOf(field.get(entity));

            AccountI18NMapper accountI18NMapper = applicationContext.getBean(AccountI18NMapper.class);
            for (Field translateField : fieldList) {
                translateField.setAccessible(true);
                AccountI18n accountI18n = new AccountI18n();
                accountI18n.setLangValue(String.valueOf(translateField.get(entity)));
                UpdateWrapper<AccountI18n> updateWrapper = new UpdateWrapper<>();
                updateWrapper.lambda()
                        .eq(AccountI18n::getBusinessId, businessId)
                        .eq(AccountI18n::getLang, LanguageContext.getLanguage())
                        .eq(AccountI18n::getLangKey, translateField.getName());
                accountI18NMapper.update(accountI18n, updateWrapper);
            }

            return result;
        }

        if (SqlCommandType.SELECT == sqlCommandType) {
            // 根据语言环境从国际化表读取数据

            if (result instanceof List) {
                System.out.println("返回的是列表");
                // 判断是否需要翻译
                List result1 = (List) result;
                if (result1.isEmpty()) {
                    System.out.println("无需翻译");
                    return result;
                }

                Object entity = result1.get(0);
                TranslateClass annotation = entity.getClass().getAnnotation(TranslateClass.class);
                if (annotation == null) {
                    System.out.println("没有需要翻译的实体，无需翻译");
                    return result;
                }

                // todo 语言的关联健需要通过注解去获取
                Field[] declaredFields = entity.getClass().getDeclaredFields();
                List<Field> fieldList = Arrays.stream(declaredFields).filter(field -> field.getAnnotation(TranslateField.class) != null).collect(Collectors.toList());
                if (fieldList.isEmpty()) {
                    System.out.println("没有需要翻译的字段，无需翻译");
                    return result;
                }

                Optional<Field> idFieldOpt = Arrays.stream(declaredFields).filter(field -> "id".equals(field.getName())).findFirst();
                if (!idFieldOpt.isPresent()) {
                    System.out.println("没id无需翻译");
                    return result;
                }

                Field idField = idFieldOpt.get();
                idField.setAccessible(true);

                // 查找翻译源
                AccountI18NMapper accountI18NMapper = applicationContext.getBean(AccountI18NMapper.class);
                QueryWrapper<AccountI18n> accountI18nQueryWrapper = new QueryWrapper<>();
                accountI18nQueryWrapper.lambda().eq(AccountI18n::getLang, LanguageContext.getLanguage());
                List<AccountI18n> accountI18NS = accountI18NMapper.selectList(accountI18nQueryWrapper);
                Map<String, AccountI18n> integerAccountI18NMap = accountI18NS.stream().collect(Collectors.toMap(AccountI18n::getBusinessId, v -> v, (o, n) -> o));

                for (Object o : result1) {
                    for (Field field : fieldList) {
                        AccountI18n accountI18N = integerAccountI18NMap.get(String.valueOf(idField.get(o)));
                        if (accountI18N != null) {
                            field.setAccessible(true);
                            field.set(o, accountI18N.getLangValue());
                        }
                    }

                }

                return result;

            } else {
                System.out.println("返回的是实体，这个场景还没考虑。。。。。。。。。，什么情况下会返回实体");

                return result;
            }

        }


        return invocation.proceed();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
